piXoneer Development Library
XDL 3.0 for C#
NXVideoView를 활용하여 동영상 플레이어를 구현해 봅니다. UAV에서 촬영하되 동영상에 Frame정보와 촬영 기하에 대한 센서 모델 정보가 함께 스트리밍되는 MPEG2TS파일을 읽어 들여 UAV 비행체의 위치, 자세, 그리고 동영상의 Foot Print를 실시간으로 도시하는 기능을 구현해봅니다.
참조 추가 방법은 “XDL_VideoView1” 튜토리얼을 참고한다.
C#
using Pixoneer.NXDL;
using Pixoneer.NXDL.NXVideo;
using Pixoneer.NXDL.NSM;
using Pixoneer.NXDL.NGR;
C#
private XVideoIO m_videoIO = null; // 동영상의 입출력을 담당할 객체 선언
private VideoState VS; // 비디오 상태를 관리하는 객체 선언
private System.Threading.Timer m_timer; // 재생 컨트롤 바 동작을 위한 타이머
private object m_lockCurFrame = new object(); // 재생 컨트롤 바와의 동기화를 위한 Lock 객체
private XTextPrinter textPrinter = null; // 텍스트를 화면에 뿌리기 위한 객체 선언
C#
public Form1()
{
InitializeComponent();
m_videoIO = new XVideoIO(); // VideoIO를 생성
VideoInit();
nxVideoLayerOverlay1.LayerVisible = true;
// 재생 컨트롤 바 동작을 위한 타이머 생성
m_timer = new System.Threading.Timer(timer_Tick);
// 타이머 옵션 변경
m_timer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
// TextPrinter 객체 생성
this.textPrinter = new XTextPrinter();
Font font = new Font("arial", 8, FontStyle.Bold);
this.textPrinter.Initialize(font);
}
C#
// PTS값을 얻기 위해 OnOrthoRender함수를 이용한다.
private bool nxVideoLayerOverlay1_OnOrthoRender(NXVideoLayer sender, NXVideoDrawArgs DrawArgs)
{
try
{
if (VS.videoChannel == null) return false;
lock (m_lockCurFrame)
{
// 현재 재생중인 화면의 PTS(Presentation TimeStamp) 값 얻어오기
Int64 pts = DrawArgs.PTS;
// PTS를 이용한 현재 재생중인 화면의 프레임 위치를 얻어오기
VS.currentFrame = VS.videoChannel.PtsToFrameNumber(pts);
if (VS.currentFrame >= VS.totalFrame) VS.currentFrame = VS.totalFrame;
if (VS.currentFrame < 0) VS.currentFrame = 0;
if (DrawArgs.FrameSensor == null) return false;
// 센서 모델링 정보 얻기
XFrameSensorParams sensor_params = DrawArgs.FrameSensor.GetModelParams();
if (sensor_params != null)
{
XVertex3d[] ptArr = new XVertex3d[5] { new XVertex3d(), new XVertex3d(), new XVertex3d(), new XVertex3d(), new XVertex3d() };
double fy = (double)DrawArgs.MetadFrame.FrameHeight / 2.0 / Math.Tan(Math.PI * 31 / 180.0);
sensor_params.FocalLength = fy;
XFrameSensor sensor = new XFrameSensor();
sensor.SetParamsEarth(sensor_params);
// 비디오 영상의 모서리 1
sensor.ImageToWorldG(new XVertex2d(0, 0), 0.0, out ptArr[0]);
// 비디오 영상의 모서리 2
sensor.ImageToWorldG(new XVertex2d(0, sensor_params.Height - 1), 0.0, out ptArr[1]);
// 비디오 영상의 모서리 3
sensor.ImageToWorldG(new XVertex2d(sensor_params.Width - 1, sensor_params.Height - 1), 0.0, out ptArr[2]);
// 비디오 영상의 모서리 4
sensor.ImageToWorldG(new XVertex2d(sensor_params.Width - 1, 0), 0.0, out ptArr[3]);
// 비디오 영상의 모서리 센터
sensor.ImageToWorldG(new XVertex2d(sensor_params.Width / 2, sensor_params.Height / 2), 0.0, out ptArr[4]);
// UAV 촬영 센서의 자세를 얻는다.
XVertex3d uav = DrawArgs.FrameSensor.GetModelParams().SensorPos;
double yaw = DrawArgs.FrameSensor.GetModelParams().SensorYaw.deg;
double pitch = DrawArgs.FrameSensor.GetModelParams().SensorPitch.deg;
double roll = DrawArgs.FrameSensor.GetModelParams().SensorRoll.deg;
// UAV 위치를 ECEF좌표계로부터 Geographic Coordiante로 변환한다.
XGeoPoint geouav = XGeoPoint.FromEcr(uav.x, uav.y, uav.z);
uav.x = geouav.lond;
uav.y = geouav.latd;
uav.z = geouav.hgt;
// UAV의 위치와 센서의 자세, 그리고 비디오 Foot Print를 화면에 도시한다.
string text = string.Empty;
text = string.Format("UAV Position : {0:000.0000000} {1:00.0000000} {2}", uav.x, uav.y, uav.z);
textPrinter.Print(text, new XVertex3d(10, 14, 0), eTextAlign.Align_Left, Color.Yellow, true, Color.Black);
text = string.Format("UAV Attitude : {0:###.0000000} {1:###.0000000} {2:###.0000000 }", yaw, pitch, roll);
textPrinter.Print(text, new XVertex3d(10, 28, 0), eTextAlign.Align_Left, Color.Yellow, true, Color.Black);
for (int i = 0; i < 4; i++)
{
text = string.Format("Video Corner {0} :{1:000.0000000} {2:00.0000000} {3:###.000000}", i+1, ptArr[i].x, ptArr[i].y, ptArr[i].z);
textPrinter.Print(text, new XVertex3d(10, 38 + 10 * (i + 1), 0), eTextAlign.Align_Left, Color.Yellow, true, Color.Black);
}
text = string.Format("Video Center :{0:000.0000000} {1:00.0000000} {2:###.000000}", ptArr[4].x, ptArr[4].y, ptArr[4].z);
textPrinter.Print(text, new XVertex3d(10, 88, 0), eTextAlign.Align_Left, Color.Yellow, true, Color.Black);
}
else
{
string text = string.Empty;
text = string.Format("No Metadata");
textPrinter.Print(text, new XVertex3d(10, 14, 0), eTextAlign.Align_Left, Color.Yellow, true, Color.Black);
return true;
}
}
}
catch (System.Exception ex)
{
Console.WriteLine(ex);
}
return default(bool);
}
참조 추가 방법은 “XDL_VideoView1” 튜토리얼을 참고한다.
C#
using Pixoneer.NXDL;
using Pixoneer.NXDL.NXVideo;
using Pixoneer.NXDL.NSM;
using Pixoneer.NXDL.NGR;
C#
private Pixoneer.NXDL.NXVideo.XVideoIO m_videoIO = null;
private VideoState VS; // 비디오 상태를 관리하는 객체 선언
private System.Threading.Timer m_timer; // 재생 컨트롤 바 동작을 위한 타이머
private object m_lockCurFrame = new object(); // 재생 컨트롤 바와의 동기화를 위한 Lock 객체
private XTextPrinter textPrinter = null; // 텍스트를 화면에 뿌리기 위한 객체 선언
C#
public MainWindow()
{
InitializeComponent();
m_videoIO = new Pixoneer.NXDL.NXVideo.XVideoIO(); // VideoIO를 생성
VideoInit();
nxVideoLayerOverlay1.LayerVisible = true;
// 재생 컨트롤 바 동작을 위한 타이머 생성
m_timer = new System.Threading.Timer(timer_Tick);
// 타이머 옵션 변경
m_timer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
// TextPrinter 객체 생성
this.textPrinter = new XTextPrinter();
Font font = new Font("arial", 8, System.Drawing.FontStyle.Bold);
this.textPrinter.Initialize(font);
}
C#
private bool nxVideoLayerOverlay1_OnOrthoRender(NXVideoLayer sender, NXVideoDrawArgs DrawArgs)
{
try
{
if (VS.videoChannel == null) return false;
lock (m_lockCurFrame)
{
// 현재 재생중인 화면이 PTS(Presentation TimeStamp) 값 얻어오기
Int64 pts = DrawArgs.PTS;
// PTS를 이용한 현재 재생중인 화면의 프레임 위치를 얻어오기
VS.currentFrame = VS.videoChannel.PtsToFrameNumber(pts);
if (VS.currentFrame >= VS.totalFrame) VS.currentFrame = VS.totalFrame;
if (VS.currentFrame < 0) VS.currentFrame = 0;
if (DrawArgs.FrameSensor == null) return false;
// 센서 모델링 정보 얻기
XFrameSensorParams sensor_params = DrawArgs.FrameSensor.GetModelParams();
if (sensor_params != null)
{
XVertex3d[] ptArr = new XVertex3d[5] { new XVertex3d(), new XVertex3d(), new XVertex3d(), new XVertex3d(), new XVertex3d() };
double fy = (double)DrawArgs.MetadFrame.FrameHeight / 2.0 / Math.Tan(Math.PI * 31 / 180.0);
sensor_params.FocalLength = fy;
XFrameSensor sensor = new XFrameSensor();
sensor.SetParamsEarth(sensor_params);
// 비디오 영상의 모서리 1
sensor.ImageToWorldG(new XVertex2d(0, 0), 0.0, out ptArr[0]);
// 비디오 영상의 모서리 2
sensor.ImageToWorldG(new XVertex2d(0, sensor_params.Height - 1), 0.0, out ptArr[1]);
// 비디오 영상의 모서리 3
sensor.ImageToWorldG(new XVertex2d(sensor_params.Width - 1, sensor_params.Height - 1), 0.0, out ptArr[2]);
// 비디오 영상의 모서리 4
sensor.ImageToWorldG(new XVertex2d(sensor_params.Width - 1, 0), 0.0, out ptArr[3]);
// 비디오 영상의 모서리 센터
sensor.ImageToWorldG(new XVertex2d(sensor_params.Width / 2, sensor_params.Height / 2), 0.0, out ptArr[4]);
// UAV 촬영 센서의 자세를 얻는다.
XVertex3d uav = DrawArgs.FrameSensor.GetModelParams().SensorPos;
double yaw = DrawArgs.FrameSensor.GetModelParams().SensorYaw.deg;
double pitch = DrawArgs.FrameSensor.GetModelParams().SensorPitch.deg;
double roll = DrawArgs.FrameSensor.GetModelParams().SensorRoll.deg;
// UAV 위치를 ECEF좌표계로부터 Geographic Coordiante로 변환한다.
XGeoPoint geouav = XGeoPoint.FromEcr(uav.x, uav.y, uav.z);
uav.x = geouav.lond;
uav.y = geouav.latd;
uav.z = geouav.hgt;
// UAV의 위치와 센서의 자세, 그리고 비디오 Foot Print를 화면에 도시한다.
string text = string.Empty;
text = string.Format("UAV Position : {0:000.0000000} {1:00.0000000} {2}", uav.x, uav.y, uav.z);
textPrinter.Print(text, new XVertex3d(10, 14, 0), eTextAlign.Align_Left, System.Drawing.Color.Yellow, true, System.Drawing.Color.Black);
text = string.Format("UAV Attitude : {0:###.0000000}{1:###.0000000}{2:###.0000000}", yaw, pitch, roll);
textPrinter.Print(text, new XVertex3d(10, 28, 0), eTextAlign.Align_Left, System.Drawing.Color.Yellow, true, System.Drawing.Color.Black);
for (int i = 0; i < 4; i++)
{
text = string.Format("Video Corner {0} :{1:000.0000000} {2:00.0000000} {3:###.000000}", i + 1, ptArr[i].x, ptArr[i].y, ptArr[i].z);
textPrinter.Print(text, new XVertex3d(10, 38 + 10 * (i + 1), 0), eTextAlign.Align_Left, System.Drawing.Color.Yellow, true, System.Drawing.Color.Black);
}
text = string.Format("Video Center :{0:000.0000000} {1:00.0000000} {2:###.000000}", ptArr[4].x, ptArr[4].y, ptArr[4].z);
textPrinter.Print(text, new XVertex3d(10, 88, 0), eTextAlign.Align_Left, System.Drawing.Color.Yellow, true, System.Drawing.Color.Black);
}
else
{
string text = string.Empty;
text = string.Format("No Metadata");
textPrinter.Print(text, new XVertex3d(10, 14, 0), eTextAlign.Align_Left, System.Drawing.Color.Yellow, true, System.Drawing.Color.Black);
return true;
}
}
}
catch (System.Exception ex)
{
Console.WriteLine(ex);
}
return default(bool);
}